
var myChart = echarts.init(<HTMLDivElement>document.getElementById('chart'));
var log_files: { file_name: string, content: string }[] = [];

function renderItem(params: echarts.EChartParams, api: echarts.EChartApi) {
    var categoryIndex = api.value(0);
    var start = api.coord([api.value(1), categoryIndex]);
    var end = api.coord([api.value(2), categoryIndex]);
    var height = api.size([0, 1]) [1] * 0.6;

    return {
        type: 'rect',
        shape: echarts.graphic.clipRectByRect({
            x: start[0],
            y: start[1] - height / 2,
            width: end[0] - start[0],
            height: height
        }, {
                x: params.coordSys.x,
                y: params.coordSys.y,
                width: params.coordSys.width,
                height: params.coordSys.height
            }),
        style: api.style()
    };
}
function seconds_to_str(value?: number) {
    if (!value) {
        return '';
    }
    value = Math.round(value);
    var hr = Math.floor(value / 3600);
    var min = Math.floor((value - hr * 3600) / 60);
    var sec = value % 60;
    var s = '';
    if (hr) {
        s += hr + 'h';
    }
    if (hr == 0 && min == 0) {
        // don't show: 0mxxs
    } else {
        s += min + 'm';
    }
    if (sec) {
        s += sec + 's';
    }
    return s;
}
var option: echarts.EChartOption = {
    tooltip: {
        formatter: function (params?: { marker: string, value?: number[] }) {
            if (!params || !params.value) {
                return '';
            }
            var s = seconds_to_str(params.value[3]);
            return params.marker +
                params.value[5] +
                '<br/>count: ' + params.value[4] +
                ', time : ' + s;
        },
    },
    title: [{
        text: 'Cycle Time',
        left: 'center',
        top: 0
    }, {
        text: '',
        top: 30,
        right: 3,
        align: 'right',
        textStyle: {
            fontSize: 12,
        }
    }],
    legend: {
        show: true,
        type: 'scroll',
        align: 'left',
        top: 30,
        data: [],
        // formatter: function (name) {
        //     return name;
        // }
    },
    dataZoom: [{
        type: 'slider',
        filterMode: 'weakFilter',
        showDataShadow: false,
        bottom: 15,
        height: 10,
        borderColor: 'transparent',
        backgroundColor: '#e2e2e2',
        labelFormatter: '',
        handleIcon: 'M10.7,11.9H9.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z', // jshint ignore:line
        handleSize: 20,
        handleStyle: {
            shadowBlur: 6,
            shadowOffsetX: 1,
            shadowOffsetY: 2,
            shadowColor: '#aaa'
        }
    }, {
        type: 'inside',
        filterMode: 'weakFilter'
    }
    ],
    visualMap: {
        dimension: 3,
        min: 0,
        max: 500,
        // range: [10, 600], // 不设置 range，则 range 默认为 [min, max], 自动随 min max 而改变
        calculable: true,
        top: 50,
        right: 0,
        itemHeight: 500,
        formatter: function (value: number) {
            return seconds_to_str(value);
        }
    },
    xAxis: {
        min: 0,
        scale: true,
        minInterval: 60,
        axisLabel: {
            formatter: function (value: number) {
                return seconds_to_str(value);
            }
        },
        splitLine: {
            show: true,
        },
        axisPointer: {
            type: 'line',
            show: true,
            label: {
                show: true,
                formatter: function (params: { value: number }) {
                    return seconds_to_str(params.value);
                }
            }
        }
    },
    yAxis: {
        splitLine: {
            show: true,
        },
        axisPointer: {
            type: 'line',
            show: true,
            label: {
                show: false
            }
        },
        data: []
    },
    series: [{
        type: 'custom',
        renderItem: renderItem,
        itemStyle: {
            normal: {
                opacity: 0.8
            }
        },
        encode: {
            x: [1, 2],
            y: 0
        },
        data: [[0, 0, 0, 0]]
    }]
};
function update_data_by_files(e: Event) {
    const t = <HTMLInputElement>e.target;
    const files = t.files;
    if (!files || !files.length) {
        return;
    }
    reset_option(files.length);
    log_files = [];
    for (var idx = 0; idx < files.length; idx++) {
        read_file(files[idx], idx);
    }
}
function read_file(file: File, idx: number) {
    var reader = new FileReader();
    reader.onload = function (e) {
        // https://github.com/Microsoft/TypeScript/issues/4163
        // or http://definitelytyped.org/guides/best-practices.html => Extending built-in types
        var result = reader.result;
        var data;
        if (result == 'data:') {
            data = '';
        } else {
            data = atob(result.split(';') [1].split(',') [1]);
        }
        log_files[idx] = {
            file_name: file.name,
            content: data
        };
        var log_list = build_log_list_from_file(data);
        set_data(file.name, log_list, idx);
    };
    reader.readAsDataURL(file);
}
function update_data() {
    option.visualMap.max = 0;
    log_files.forEach((log, idx) => {
        var log_list = build_log_list_from_file(log.content);
        set_data(log.file_name, log_list, idx);
    });
}
function build_log_list_from_file(content: string) {
    var log_list: log.Log[] = [];
    var ln = 0;
    var count = 0;
    var time_obj: Date | null = null;
    var time: number | null = null;
    var last_time: number | null = null;
    const line_patt = RegExp((document.getElementById("line")! as HTMLInputElement).value);
    const time_patt = RegExp((document.getElementById("time")! as HTMLInputElement).value);
    content.split('\n').forEach(function (line, li) {
        ln += 1;
        line = line.trim();
        if (line.search(line_patt) < 0) {
            return;
        }
        if (!time_patt.test(line)) {
            return;
        }
        count += 1;
        let m = line.split(time_patt);
        let start_i = line.indexOf(m[1]);
        var end_i = line.length;
        if (m[m.length - 1] != '') {
            end_i = line.indexOf(m[m.length - 1]);
        }
        time = Date.parse(line.slice(start_i, end_i));
        time_obj = new Date(time);
        if (last_time == null) {
            last_time = time;
        }
        log_list.push({
            count: count,
            dt: Math.round((time - last_time) / 1000),
            time: time_obj.toLocaleString()
        });
        last_time = time;
    });
    return log_list;
}
function reset_option(n: number) {
    option.visualMap.max = 0;
    option.legend.data = [];
    option.yAxis.data = [];
    option.series = [];
    for (var i = 0; i < n; i++) {
        option.series.push({
            type: 'custom',
            renderItem: renderItem,
            itemStyle: {
                normal: {
                    opacity: 0.8
                }
            },
            encode: {
                x: [1, 2],
                y: 0
            },
            data: [[0, 0, 0, 0]]
        });
    }
}
function set_data(file_name: string, log_list: log.Log[], idx: number) {
    var baseTime = 0;
    var max_dt = 0;
    var data = log_list.map(
        function (i) {
            max_dt = Math.max(max_dt, i.dt);
            return [
                idx,
                baseTime,
                baseTime += i.dt,
                i.dt,
                i.count,
                i.time
            ];
        });
    if (data.length == 0) {
        data = [[0, 0, 0, 0]];
    }
    option.visualMap.max = Math.max(option.visualMap.max, max_dt);
    update_data_range_selected(option, 0, option.visualMap.max);
    var legend = (idx + 1) + '#' + file_name;
    option.legend.data[idx] = legend;
    option.yAxis.data![idx] = legend;
    option.series[idx].name = legend;
    option.series[idx].data = data;
    myChart.setOption(option, true, false);
}
myChart.setOption(option);
document.getElementById('log_files')!.addEventListener('change', update_data_by_files);
myChart.on('datarangeselected', function (params) {
    // console.log(params);
    let min = params.selected[0];
    let max = params.selected[1];
    update_data_range_selected(option, min, max);
    myChart.setOption(option);
});
function update_data_range_selected(option: echarts.EChartOption, min: number, max: number) {
    let data_in_range = 0;
    let data_total = 0;
    option.series.forEach((s) => {
        let d = count_data_in_range(min, max, s.data);
        data_in_range += d.data_in_range;
        data_total += d.data_total;
    });
    let text = data_in_range + '/' + data_total + ' ' + (data_in_range / data_total * 100).toFixed(1) + '%';
    option.title[1].text = text;
    return text;
}
function count_data_in_range(min: number, max: number, data: (number | string) [][]) {
    let data_in_range = 0;
    let data_total = 0;
    data.forEach((d, idx) => {
        if (idx == 0) {
            return;
        }
        // @ts-ignore
        let dt = d[3];
        // @ts-ignore
        if (dt >= min && dt <= max) {
            data_in_range += 1;
        }
        data_total += 1;
    });
    return { data_in_range, data_total };
}

function test() {
    log_files = [
        {
            file_name: 'client1-reboot-2017-0311.log',
            content: '\
Sat Mar 11 03:55:47 CST 2017\n\
Sat Mar 11 03:59:00 CST 2017\n\
Sat Mar 11 04:02:14 CST 2017\n\
Sat Mar 11 04:05:27 CST 2017\n\
Sat Mar 11 04:08:51 CST 2017\n\
Sat Mar 11 04:12:07 CST 2017\n\
Sat Mar 11 04:15:22 CST 2017\n\
Sat Mar 11 04:18:16 CST 2017\n\
Sat Mar 11 04:21:13 CST 2017\n\
Sat Mar 11 04:24:39 CST 2017'
        },
        {
            file_name: 'client2-reboot-2017-0312.log',
            content: '\
Sun Mar 12 00:46:32 CST 2017\n\
Sun Mar 12 00:50:01 CST 2017\n\
Sun Mar 12 00:53:25 CST 2017\n\
Sun Mar 12 00:56:55 CST 2017\n\
Sun Mar 12 01:00:34 CST 2017\n\
Sun Mar 12 01:04:15 CST 2017\n\
Sun Mar 12 01:07:22 CST 2017\n\
Sun Mar 12 01:10:38 CST 2017\n\
Sun Mar 12 01:14:06 CST 2017\n\
Sun Mar 12 01:17:39 CST 2017'
        },
        {
            file_name: 'client3-reboot-2017-0315.log',
            content: '\
Wed Mar 15 03:25:28 CST 2017\n\
Wed Mar 15 03:29:33 CST 2017\n\
Wed Mar 15 03:33:50 CST 2017\n\
Wed Mar 15 03:38:04 CST 2017\n\
Wed Mar 15 03:41:54 CST 2017\n\
Wed Mar 15 03:46:08 CST 2017\n\
Wed Mar 15 03:51:13 CST 2017\n\
Wed Mar 15 03:55:51 CST 2017\n\
Wed Mar 15 04:00:04 CST 2017\n\
Wed Mar 15 04:04:13 CST 2017'
        },
    ];
    reset_option(log_files.length);
    update_data();
}
test();